home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / minrec.zip / RECHOOK.C < prev    next >
C/C++ Source or Header  |  1993-04-30  |  10KB  |  308 lines

  1. // ************************************************************************
  2. // MODULE    : RecHook.C
  3. // PURPOSE   :
  4. // FUNCTIONS :
  5. //   DllEntryPoint        - main DLL entry point
  6. //   StartJournalRecord   - starts the journal record hook
  7. //   StopJournalRecord    - stops the journal record hook
  8. //   StartJournalPlayback - starts the journal playback hook
  9. //   StopJournalPlayback  - stops the journal playback hook
  10. // COMMENTS  :
  11. // ************************************************************************
  12. #define   STRICT
  13. #include <Windows.H>
  14. #include "RecHook.H"
  15.  
  16. // Internal Defines
  17. // -----------------------------------------------------------------------
  18. #define FILENAME "JOURNAL.BIN"  // File used to record/play messages
  19.  
  20. typedef struct GLOBAL_STRUCT {
  21.   BOOL      fRecording;
  22.   BOOL      fPlaying;
  23.   BOOL      fStopRecording;
  24.   BOOL      fStopPlaying;
  25.   UINT      PlayedMsgCount;
  26.   UINT      RecordedMsgCount;
  27.   DWORD     BaseMsgTime;
  28.   DWORD     LastMsgTime;
  29.   HFILE     hFile;
  30.   OFSTRUCT  OFStruct;
  31.   EVENTMSG  EventMsg;
  32.   HHOOK     hHookRecord;
  33.   HHOOK     hHookPlayback;
  34.   HINSTANCE hInstance;
  35. } GLOBAL, *PGLOBAL;
  36.  
  37. // Global Data
  38. // -----------------------------------------------------------------------
  39. GLOBAL  Global;                // various global data
  40.  
  41. // Internal Function Prototypes
  42. // -----------------------------------------------------------------------
  43. LRESULT CALLBACK JournalRecordProc  ( int, WPARAM, LPARAM );
  44. LRESULT CALLBACK JournalPlaybackProc( int, WPARAM, LPARAM );
  45.  
  46.  
  47. // ************************************************************************
  48. // FUNCTION : DllEntryPoint( HINSTANCE, DWORD, LPVOID )
  49. // PURPOSE  : DllEntryPoint is called by Windows when the DLL is entered
  50. //            via a "Process Attach", "Thread Attach", "Thread Detach" or a
  51. //            "Process Detach".
  52. // ************************************************************************
  53. BOOL WINAPI
  54. DllEntryPoint( HINSTANCE hInstanceDll, DWORD dwReason, LPVOID lpvReserved )
  55. {
  56.   switch( dwReason ) {
  57.  
  58.     case DLL_PROCESS_ATTACH:
  59.       Global.fRecording    = FALSE;
  60.       Global.fPlaying      = FALSE;
  61.       Global.hInstance     = hInstanceDll;
  62.       break;
  63.  
  64.   }
  65.  
  66.   return( TRUE );
  67.   UNREFERENCED_PARAMETER( lpvReserved );
  68. }
  69.  
  70.  
  71. // ************************************************************************
  72. // FUNCTION : StartJournalRecord()
  73. // PURPOSE  :
  74. // ************************************************************************
  75. VOID WINAPI
  76. StartJournalRecord()
  77. {
  78.   // Do not allow recording while playing back
  79.   if( Global.fPlaying ) {
  80.     MessageBox( GetFocus(), TEXT("Sorry, Currently Playing!"), NULL, MB_OK );
  81.     return;
  82.   }
  83.  
  84.   // Create journal record file
  85.   Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct,
  86.                    OF_CREATE | OF_WRITE | OF_EXIST );
  87.  
  88.   // Initialize the recorded message count to zero and set recording flag
  89.   Global.RecordedMsgCount = 0;
  90.   Global.fRecording       = TRUE;
  91.  
  92.   // Set the Journal Record hook.
  93.   Global.hHookRecord = SetWindowsHookEx( WH_JOURNALRECORD,
  94.                          JournalRecordProc, Global.hInstance, 0 );
  95.  
  96.   return;
  97. }
  98.  
  99.  
  100. // ************************************************************************
  101. // FUNCTION : JournalRecordProc()
  102. // PURPOSE  :
  103. // ************************************************************************
  104. LRESULT CALLBACK
  105. JournalRecordProc( int nCode, WPARAM wParam, LPARAM lParam )
  106. {
  107.   if( nCode < 0  || Global.fStopRecording )
  108.     return( CallNextHookEx( Global.hHookRecord, nCode, wParam, lParam ) );
  109.  
  110.   switch( nCode ) {
  111.  
  112.     case HC_ACTION: {
  113.       LPEVENTMSG lpEventMsg;
  114.  
  115.       // write the event message to the Recorded Journal file
  116.       Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct,
  117.                        OF_REOPEN | OF_WRITE );
  118.       _llseek( Global.hFile,
  119.         (LONG) ( sizeof(EVENTHEADER)
  120.         + (Global.RecordedMsgCount * sizeof(EVENTMSG)) ), 0 );
  121.       _lwrite( Global.hFile, (LPCSTR) lParam, sizeof(EVENTMSG) );
  122.       _lclose( Global.hFile );
  123.       lpEventMsg = (LPEVENTMSG) lParam;
  124.       Global.RecordedMsgCount++;
  125.       if( Global.RecordedMsgCount == 1)
  126.         Global.BaseMsgTime = lpEventMsg->time;
  127.       break;
  128.     }
  129.  
  130.     case HC_SYSMODALON:
  131.       // halt recording
  132.       Global.fStopRecording = TRUE;
  133.       break;
  134.  
  135.     case HC_SYSMODALOFF:
  136.       // resume recording
  137.       Global.fStopRecording = FALSE;
  138.       break;
  139.  
  140.   }
  141.  
  142.   return( CallNextHookEx( Global.hHookRecord, nCode, wParam, lParam ) );
  143.   UNREFERENCED_PARAMETER( wParam );
  144. }
  145.  
  146.  
  147. // ************************************************************************
  148. // FUNCTION : StopJournalRecord()
  149. // PURPOSE  :
  150. // ************************************************************************
  151. VOID WINAPI
  152. StopJournalRecord()
  153. {
  154.   EVENTHEADER EventHeader;
  155.  
  156.   // Remove the Journal Record hook if recording
  157.   if( Global.fRecording ) {
  158.     UnhookWindowsHookEx( Global.hHookRecord );
  159.  
  160.     // Clear recording flag
  161.     Global.fRecording = FALSE;
  162.  
  163.     // Copy Recorded Journal header data to temporary buffer
  164.     EventHeader.RecordedMsgCount = Global.RecordedMsgCount;
  165.     EventHeader.BaseMsgTime      = Global.BaseMsgTime;
  166.  
  167.     // Open Recorded Journal file and update the file header and close
  168.     //  the file
  169.     Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct, OF_WRITE );
  170.     _llseek( Global.hFile, 0L, 0 );
  171.     _lwrite( Global.hFile, (LPCSTR) &EventHeader, sizeof(EVENTHEADER) );
  172.     _lclose( Global.hFile );
  173.   }
  174.  
  175.   return;
  176. }
  177.  
  178.  
  179. // ************************************************************************
  180. // FUNCTION : StartJournalPlayback()
  181. // PURPOSE  :
  182. // ************************************************************************
  183. VOID WINAPI
  184. StartJournalPlayback()
  185. {
  186.   EVENTHEADER EventHeader;
  187.  
  188.   // Allow infinite playback loop
  189.   if( Global.fRecording ) {
  190.     StopJournalRecord();
  191.     MessageBox( GetFocus(), TEXT("Infinite Playback Loop Recorded!"),
  192.       TEXT("Warning"), MB_ICONEXCLAMATION | MB_OK );
  193.     return;
  194.   }
  195.  
  196.   // Open Recorded Journal file and read the file header
  197.   Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct, OF_READ );
  198.   _llseek( Global.hFile, 0L, 0 );
  199.   _lread( Global.hFile, (LPVOID) &EventHeader, sizeof(EVENTHEADER) );
  200.   _lclose( Global.hFile );
  201.  
  202.   // store the header values
  203.   Global.RecordedMsgCount = EventHeader.RecordedMsgCount;
  204.   Global.BaseMsgTime      = EventHeader.BaseMsgTime;
  205.   Global.LastMsgTime      = EventHeader.BaseMsgTime;
  206.  
  207.   // If no messages were recorded, none to play back.
  208.   if( Global.RecordedMsgCount == 0 ) {
  209.     MessageBox( GetFocus(), TEXT("Nothing Recorded!"), NULL, MB_OK);
  210.     return;
  211.   }
  212.  
  213.   // Initialize the played message count to zero and set the play flag
  214.   Global.PlayedMsgCount = 0;
  215.   Global.fPlaying       = TRUE;
  216.  
  217.   // Get the first recorded message from the file and store it
  218.   Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct,
  219.                    OF_REOPEN | OF_READ );
  220.   _llseek( Global.hFile, (LONG) sizeof(EVENTHEADER), 0 );
  221.   _lread( Global.hFile, (LPVOID) &(Global.EventMsg), sizeof(EVENTMSG) );
  222.   _lclose( Global.hFile );
  223.  
  224.   // Set the Journal Playback hook
  225.   Global.hHookPlayback = SetWindowsHookEx( WH_JOURNALPLAYBACK,
  226.                            JournalPlaybackProc, Global.hInstance, 0 );
  227.  
  228.   return;
  229. }
  230.  
  231.  
  232. // ************************************************************************
  233. // FUNCTION : JournalPlaybackProc()
  234. // PURPOSE  :
  235. // ************************************************************************
  236. LRESULT CALLBACK
  237. JournalPlaybackProc( int nCode, WPARAM wParam, LPARAM lParam )
  238. {
  239.   if( nCode < 0  || Global.fStopPlaying )
  240.     return( CallNextHookEx( Global.hHookPlayback, nCode, wParam, lParam ) );
  241.  
  242.   switch( nCode ) {
  243.  
  244.    case HC_GETNEXT: {
  245.       LRESULT SleepTime = Global.EventMsg.time - Global.LastMsgTime;
  246.  
  247.       // copy the current ready event message to lParam
  248.       CopyMemory( (PVOID) lParam, (CONST VOID*) &(Global.EventMsg),
  249.         sizeof(EVENTMSG) );
  250.       Global.LastMsgTime = Global.EventMsg.time;
  251.       return( SleepTime );
  252.     }
  253.  
  254.     case HC_SKIP: {
  255.       if( ++Global.PlayedMsgCount > Global.RecordedMsgCount ) {
  256.         StopJournalPlayback();
  257.         return( (LRESULT) 0L );
  258.       }
  259.       else {
  260.         // Get the next recorded message from the file and store it
  261.         //  in the static buffer for the next HC_GETNEXT message
  262.         Global.hFile = OpenFile( (LPCSTR) FILENAME, &Global.OFStruct,
  263.                          OF_REOPEN | OF_READ );
  264.         _llseek( Global.hFile,
  265.           (LONG) ( sizeof(EVENTHEADER)
  266.           + (Global.PlayedMsgCount * sizeof(EVENTMSG)) ), 0 );
  267.         _lread( Global.hFile, (LPVOID) &(Global.EventMsg),
  268.           sizeof(EVENTMSG) );
  269.         _lclose( Global.hFile );
  270.         break;
  271.       }
  272.     }
  273.  
  274.     case HC_SYSMODALON:
  275.       // halt playback
  276.       Global.fStopPlaying = TRUE;
  277.       break;
  278.  
  279.     case HC_SYSMODALOFF:
  280.       // resume playback
  281.       Global.fStopPlaying = FALSE;
  282.       break;
  283.  
  284.   }
  285.  
  286.   return( CallNextHookEx( Global.hHookPlayback, nCode, wParam, lParam ) );
  287.   UNREFERENCED_PARAMETER( wParam );
  288. }
  289.  
  290.  
  291. // ************************************************************************
  292. // FUNCTION : StopJournalPlayback()
  293. // PURPOSE  :
  294. // ************************************************************************
  295. VOID WINAPI
  296. StopJournalPlayback()
  297. {
  298.   // Remove the Playback Journal hook if playing
  299.   if( Global.fPlaying ) {
  300.     UnhookWindowsHookEx( Global.hHookPlayback );
  301.  
  302.     // Clear playback flag
  303.     Global.fPlaying = FALSE;
  304.   }
  305.  
  306.   return;
  307. }
  308.